package org.linlinjava.litemall.wx.service;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.linlinjava.litemall.core.util.HttpUtil;
import org.linlinjava.litemall.db.domain.*;
import org.linlinjava.litemall.db.service.*;
import org.linlinjava.litemall.wx.aiweb.WxAiChatController;
import org.linlinjava.litemall.wx.util.ChatUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class ChatGPTService {

    private final Log logger = LogFactory.getLog(ChatGPTService.class);
    @Autowired
    private LemonlaActorService actorService;
    @Autowired
    private LitemallUserService userService;
    @Autowired
    private LemonlaDialogueService dialogueService;
    @Autowired
    private LemonlaUserPointService userPointService;
    @Autowired
    private LemonlaSessionService sessionService;

    @Autowired
    private Environment environment;
    
    public String chat(LemonlaSession session, String content) {
//        数据格式 [
//                {"role": "system","content":"你是一个聊天机器人，你不情愿地用讽刺的回答来回答问题："},
//                {"role": "user", "content": "人为什么要吃饭"},
//            ]
        //  system   = 角色描述 + 场景描述 + 历史对话 + content

        final Integer userId = session.getUserId();
        final UserVo user = userService.findUserVoById(userId);

        //step 1 角色描述+场景描述
        final Integer actorId = session.getActorId();
        LemonlaActor actor = actorService.findByIdWithDes(actorId);
        logger.info("actor = " + actor.getId());
        String description = actor.getDescription();
//        if (description.contains(ChatUtil.USER_NAME_HOLDER)) {
//            description = description.replace(ChatUtil.USER_NAME_HOLDER,user.getNickname());
//        }
//        if (description.contains(ChatUtil.NICK_NAME_HOLDER)) {
//            description = description.replace(ChatUtil.NICK_NAME_HOLDER,session.getNickname());
//        }
        if (StringUtils.isNotEmpty(session.getSceneInformation())) {
            description+=session.getSceneInformation();
        }

        return chatToGpt(session, content, userId, description);
    }


    /**
     * 和chatgpt聊天
     *
     * @param session 会话
     * @param content 本次输入
     * @param userId 用户id
     * @param description 会话描述
     */
    private String chatToGpt(LemonlaSession session, String content, Integer userId, String description) {
        JSONArray messages = new JSONArray();
        JSONObject systemDia = new JSONObject();
        systemDia.put(ChatUtil.ROLE,ChatUtil.SYS);
        systemDia.put(ChatUtil.CONTENT, description);
        messages.add(systemDia);

        //历史聊天记录

        final List<LemonlaDialogue> lemonlaDialogues = dialogueService.queryBySessionId(session.getId());
        for (LemonlaDialogue lemonlaDialogue : lemonlaDialogues) {
            JSONObject userDia = new JSONObject();
            userDia.put(ChatUtil.ROLE,lemonlaDialogue.getRoleName());
            userDia.put(ChatUtil.CONTENT,lemonlaDialogue.getDialogueContent());
            messages.add(userDia);
        }

        //本次输入
        JSONObject currentDia = new JSONObject();
        currentDia.put(ChatUtil.ROLE,ChatUtil.USER);
        currentDia.put(ChatUtil.CONTENT, content);
        messages.add(currentDia);

        //最大序列号理论上应该等于历史记录总数  但是这里这样写是不严谨的
        Integer maxSerialNumber = lemonlaDialogues.size();

        //记录用户输入
        LemonlaDialogue dialogue = new LemonlaDialogue();
        dialogue.setRole((short) 0);
        dialogue.setSessionId(session.getId());
        dialogue.setSerialNumber(++maxSerialNumber);
        logger.info("content = " + content);
        dialogue.setDialogueContent(content);
        dialogueService.add(dialogue);
        userPointService.consume(userId, content);
        long startTime = System.currentTimeMillis();
        //CHATGPT交互
        String response = HttpUtil.doPost(environment.getProperty("lemonla.chatgpt.url", "http://23.94.59.186:5000"), messages.toJSONString());
        long endTime = System.currentTimeMillis();
        long duration = endTime-startTime;
        logger.info("request took " + duration +" milliseconds and response = " +response);
        //记录chatGPT返回
        LemonlaDialogue assistantDia = new LemonlaDialogue();
        assistantDia.setRole((short) 1);
        assistantDia.setSessionId(session.getId());
        assistantDia.setSerialNumber(++maxSerialNumber);
        assistantDia.setDialogueContent(response);
        dialogueService.add(assistantDia);
        userPointService.consume(userId,response);
        return response;
    }

    public String chatOnce(LemonlaSession session, JSONObject params) {
        final Integer actorId = session.getActorId();
        final Integer userId = session.getUserId();
        LemonlaActor actor = actorService.findByIdWithDes(actorId);
        String content = "";
        if (StringUtils.isEmpty(session.getSceneInformation())) {
            String description = actor.getDescription();
            for (String s : params.keySet()) {
                String value = params.getString(s);
                if (s.startsWith("@") && s.endsWith("@")) {
                    value = smlltrick(value);
                }
                if (description.contains("##" + s)) {
                    description = description.replace("##" + s, value);
                }
            }
            session.setSceneInformation(description);
            sessionService.updateById(session);
        } else {
            content = params.getString("content");
        }
        return chatToGpt(session, content, userId, session.getSceneInformation());
    }

    private String smlltrick(String value) {
        String result = "";
        for (int i = 0; i < value.length(); i++) {
            String c = value.substring(i,i+1);
            result += "'"+c+"',";
        }
        result = result.substring(0,result.length() - 1);
        return result;
    }
}
